package com.onairm.baselibrary.tv;

import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.View;

/**
 * Created by bqy on 2018/4/3.
 */

public class FirstClassView extends RecyclerView implements View.OnClickListener, View.OnFocusChangeListener{

    private boolean mIsSelectFirstVisiblePosition;
    private boolean mShouldReverseLayout = true;
    private int mSelectedPosition = 0;
    private boolean mHasFocusWithPrevious = false;
    private boolean mOptimizeLayout;
    private final Rect mTempRect = new Rect();

    public FirstClassView(Context context) {
        super(context);
    }

    public FirstClassView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FirstClassView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        mHasFocusWithPrevious = mHasFocusWithPrevious || hasFocus();
//        Log.i("TAG","onLayout...start hasFocus()="+mHasFocusWithPrevious + " changed="+changed + " ,mShouldReverseLayout="+ mShouldReverseLayout);

        final boolean requestLayout = !mOptimizeLayout || (changed || mShouldReverseLayout);
        final boolean layoutAfterFocus;
        if(requestLayout) {
            super.onLayout(changed, l, t, r, b);
            mShouldReverseLayout = false;

            layoutAfterFocus = hasFocus();
            if(!layoutAfterFocus) {
                if(mSelectedPosition < 0) {
                    mSelectedPosition = getFirstVisiblePosition();
                } else if(mSelectedPosition >= getItemCount()) {
                    mSelectedPosition = getLastVisiblePosition();
                }
                if(mHasFocusWithPrevious && getPreserveFocusAfterLayout()) {
                    requestDefaultFocus();
                } else {
                    setItemActivated(mSelectedPosition);
                }
            }
        } else {
            layoutAfterFocus = hasFocus();
        }
        mHasFocusWithPrevious = false;
    }

    public void setItemActivated(int position) {
        ViewHolder holder;
        if (position != mSelectedPosition) {
            holder = findViewHolderForLayoutPosition(mSelectedPosition);
            if (null != holder && holder.itemView.isActivated()) {
                holder.itemView.setActivated(false);
            }
            mSelectedPosition = position;
        }
        holder = findViewHolderForLayoutPosition(position);
        if (null != holder && !holder.itemView.isActivated()) {
            holder.itemView.setActivated(true);
        }
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {
        if (gainFocus) {
            setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
        } else {
            setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
        }
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    }

    @Override
    public void onFocusChange(View itemView, boolean hasFocus) {
        if(null != itemView && itemView != this) {
            final int position = getChildAdapterPosition(itemView);
            itemView.setSelected(hasFocus);

            if (upOrDown == 1){
                itemView.setSelected(true);
                upOrDown = 0;
            }else if (upOrDown== 2){
                itemView.setSelected(false);
                upOrDown = 0;
            }

            if (hasFocus) {
                mSelectedPosition = position;
                if(itemView.isActivated()) {
                    itemView.setActivated(false);
                }
                if(null != mOnItemListener)
                    mOnItemListener.onItemSelected(FirstClassView.this, itemView, position);
            } else {
                itemView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if(!hasFocus()) {
//                            if(mIsMenu) {
//                                // 解决选中后无状态表达的问题，selector中使用activated代表选中后焦点移走
//                                itemView.setActivated(true);
//                            }
//                            //模拟TvRecyclerView失去焦点
                            onFocusChanged(false, FOCUS_DOWN, null);
                        }
                    }
                }, 0);
                if(null != mOnItemListener)
                    mOnItemListener.onItemPreSelected(FirstClassView.this, itemView, position);
            }
        }
    }

    private int upOrDown = 0;  // 当焦点在RecyclerView之后，按下的是上键  还是  下键

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        boolean result = super.dispatchKeyEvent(event);
        if (!result) {
            switch (event.getAction()) {
                case KeyEvent.ACTION_DOWN:
                    result = null != mOnInBorderKeyEventListener && handleKeyDown(event.getKeyCode(), event);
                    if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
                        upOrDown = 1;
                    } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {
                        upOrDown = 2;
                    }
                    break;
                case KeyEvent.ACTION_UP:
                    result = onKeyUp(event.getKeyCode(), event);
                    break;
            }
        }
        return result;
    }

    public int getFirstVisiblePosition() {
        if (getChildCount() == 0)
            return 0;
        else
            return getChildAdapterPosition(getChildAt(0));
    }

    public int getLastVisiblePosition() {
        final int childCount = getChildCount();
        if (childCount == 0)
            return 0;
        else
            return getChildAdapterPosition(getChildAt(childCount - 1));
    }

    public int getItemCount() {
        if (null != getAdapter()) {
            return getAdapter().getItemCount();
        }
        return 0;
    }

    /**
     * 处理onKeyDown等事件
     *
     * @param keyCode
     * @param event
     * @return
     */
    private boolean handleKeyDown(int keyCode, KeyEvent event) {
        int direction = keyCode2Direction(keyCode);

        if (direction == -1 || null == mOnInBorderKeyEventListener) {
            return false;
        }

        final View nextFocusedView = findNextFocus(direction);
        if (hasInBorder(direction, nextFocusedView)) {
            return mOnInBorderKeyEventListener.onInBorderKeyEvent(direction, keyCode, event);
        }
        if (null != nextFocusedView) {
            nextFocusedView.requestFocus();
        }
        return true;
    }

    /**
     * keycode值转成Direction值
     *
     * @param keyCode
     * @return
     */
    private int keyCode2Direction(int keyCode) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_DOWN:
                return FOCUS_DOWN;

            case KeyEvent.KEYCODE_DPAD_RIGHT:
                return FOCUS_RIGHT;

            case KeyEvent.KEYCODE_DPAD_LEFT:
                return FOCUS_LEFT;

            case KeyEvent.KEYCODE_DPAD_UP:
                return FOCUS_UP;

            default:
                return -1;
        }
    }

    /**
     * 判断选中的item是否到达边界
     */
    private boolean hasInBorder(int direction, View nextFocusedView) {
        if (null != nextFocusedView)
            return false;
        Log.i("TAG", "hasInBorder...direction=" + direction);
        switch (direction) {
            case FOCUS_DOWN:
                return !ViewCompat.canScrollVertically(this, 1);

            case FOCUS_UP:
                return !ViewCompat.canScrollVertically(this, -1);

            case FOCUS_LEFT:
                return ViewCompat.canScrollHorizontally(this, -1);

            case FOCUS_RIGHT:

                return !ViewCompat.canScrollHorizontally(this, 1);

            default:
                return false;
        }
    }

    @Override
    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
        Log.i("TAG", "direction..." + direction);
        if (null == getFocusedChild()) {
            //请求默认焦点
            requestDefaultFocus();
        }
        return false;
    }

    public void requestDefaultFocus() {
        if (!mIsSelectFirstVisiblePosition) {
            setSelection(mSelectedPosition);
        } else {
            setSelection(getFirstVisiblePosition());
        }
    }

    public void setSelection(int position) {
        if (null == getAdapter() || position < 0 || position >= getItemCount()) {
            return;
        }

        View view = getChildAt(position - getFirstVisiblePosition());
        if (null != view) {
            if (!hasFocus()) {
                //模拟TvRecyclerView获取焦点
                onFocusChanged(true, FOCUS_DOWN, null);
            }
            view.requestFocus();
        } else {
//            TvSmoothScroller scroller = new TvSmoothScroller(getContext(), true, true, mSelectedItemOffsetStart);
//            scroller.setTargetPosition(position);
//            getLayoutManager().startSmoothScroll(scroller);
        }
    }

    @Override
    public void onChildAttachedToWindow(View child) {
        if(child.isClickable() && !ViewCompat.hasOnClickListeners(child)) {
            child.setOnClickListener(this);
        }
        if(child.isFocusable() && null == child.getOnFocusChangeListener()) {
            child.setOnFocusChangeListener(this);
        }
    }

    /**
     * 查找下个可获取焦点的view
     *
     * @param direction
     * @return
     */
    private View findNextFocus(int direction) {
        return FocusFinder.getInstance().findNextFocus(this, getFocusedChild(), direction);
    }

    public void setSelectFirstVisiblePosition(boolean selectFirstVisiblePosition) {
        mIsSelectFirstVisiblePosition = selectFirstVisiblePosition;
    }

    private OnItemListener mOnItemListener;

    private OnInBorderKeyEventListener mOnInBorderKeyEventListener;

    public void setOnItemListener(OnItemListener mOnItemListener) {
        this.mOnItemListener = mOnItemListener;
    }

    public void setOnInBorderKeyEventListener(OnInBorderKeyEventListener mOnInBorderKeyEventListener) {
        this.mOnInBorderKeyEventListener = mOnInBorderKeyEventListener;
    }

    @Override
    public void onClick(View itemView) {
        if(null != mOnItemListener && this != itemView) {
            mOnItemListener.onItemClick(FirstClassView.this, itemView, getChildAdapterPosition(itemView));
        }
    }
    public interface OnItemListener {
        void onItemPreSelected(FirstClassView parent, View itemView, int position);

        void onItemSelected(FirstClassView parent, View itemView, int position);

        void onItemClick(FirstClassView parent, View itemView, int position);
    }

    public interface OnInBorderKeyEventListener {
        boolean onInBorderKeyEvent(int direction, int keyCode, KeyEvent event);
    }
}
